package com.dbflow5.processor.utils;

import com.dbflow5.processor.ProcessorManager;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;

import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import java.lang.annotation.Annotation;

/**
 * element extensions
 */
public class ElementExtensions {
    public static TypeElement toTypeElement(Element element, ProcessorManager manager) {
        if (element != null) {
            if (manager == null) {
                manager = ProcessorManager.manager;
            }
            return toTypeElement(element.asType(), manager);
        }
        return null;
    }

    public static TypeElement toTypeErasedElement(Element element, ProcessorManager manager) {
        if (element != null) {
            if (manager == null) {
                manager = ProcessorManager.manager;
            }
            return toTypeElement(erasure(element.asType(), manager), manager);
        }
        return null;
    }

    public static String simpleString(Element element) {
        return element.getSimpleName().toString();
    }

    public static TypeElement toTypeElement(TypeMirror typeMirror, ProcessorManager manager) {
        if (manager == null) {
            manager = ProcessorManager.manager;
        }
        return manager.elements.getTypeElement(typeMirror.toString());
    }

    public static TypeMirror erasure(TypeMirror typeMirror, ProcessorManager manager) {
        if (manager == null) {
            manager = ProcessorManager.manager;
        }
        return manager.typeUtils.erasure(typeMirror);
    }

    // TypeName
    public static TypeElement toTypeElement(TypeName typeName, ProcessorManager manager) {
        if (manager == null) {
            manager = ProcessorManager.manager;
        }
        return manager.elements.getTypeElement(typeName.toString());
    }

    public static <T extends Annotation> T annotation(Class<T> clazz, Element element) {
        if (element != null) {
            return element.getAnnotation(clazz);
        }
        return null;
    }

    public static PackageElement getPackage(Element element, ProcessorManager manager) {
        if (manager == null) {
            manager = ProcessorManager.manager;
        }
        return manager.elements.getPackageOf(element);
    }

    public static ClassName toClassName(Element element, ProcessorManager manager) {
        if (manager == null) {
            manager = ProcessorManager.manager;
        }

        if (element == null) {
            return null;
        } else if (element instanceof TypeElement) {
            return ClassName.get((TypeElement) element);
        } else {
            return ElementUtility.getClassName(element.asType().toString(), manager);
        }
    }

    public static boolean isOneOf(TypeName typeName, Class<?>... kClass) {
        if (typeName != null) {
            for (Class<?> clazz : kClass) {
                if (com.squareup.javapoet.TypeName.get(clazz) == typeName) {
                    return true;
                }
            }
        }
        return false;
    }

    public static TypeName rawTypeName(TypeName typeName) {
        if (typeName instanceof ParameterizedTypeName) {
            return ((ParameterizedTypeName) typeName).rawType;
        }
        return typeName;
    }
}